#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <globals.h>
#include "application.h"

#include <QDockWidget>
#include <QActionGroup>
#include <QFile>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QFormLayout>
#include <QWheelEvent>
#include <QSlider>
#include <QLabel>

#include "src/widgets/toolaction.h"
#include "src/drawingview.h"
#include "src/drawingviewcontainer.h"
#include "src/dialogs/dlgnewdocument.h"
#include "src/dialogs/viewdocuments.h"
#include "src/widgets/toolswidget.h"

#include <Tool>
#include <ToolCategory>
#include <StateManager>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    initMainWindowProperties();
    initUndoRedo();
    initMenus();
    initMainToolbar();
    initDrawingViewContainer();
    initToolsWidgets();
    initDocumentsView();
    initStatusBar();

    statusBar()->showMessage("Ready");
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::wheelEvent(QWheelEvent *pEvent)
{
    QPointer<Document> doc = Application::app().activeDocument();

    if(doc)
    {
        int d = pEvent->delta();
        float factor = (float)d/1200.0f;

        doc->setZoom(doc->zoom() + factor);
        doc->ownerView()->update();
    }
}

void MainWindow::initMenus()
{
    ui->actionShowHideTools->setCheckable(true);
    ui->actionShowHideDocumentsView->setCheckable(true);

    ui->actionClose->setDisabled(true);
    connect(&Application::app(), SIGNAL(documentCreated(QPointer<Document>)),
            this, SLOT(updateWidgetsDependentOfDocumentExistion(QPointer<Document>)));

    connect(&Application::app(), SIGNAL(documentRemoved(QPointer<Document>)),
            this, SLOT(updateWidgetsDependentOfDocumentExistion(QPointer<Document>)));

    Q_ASSERT(m_undoAction);
    Q_ASSERT(m_redoAction);

    ui->menuEdit->addAction(m_undoAction);
    ui->menuEdit->addAction(m_redoAction);
}

void MainWindow::initMainToolbar()
{
    ui->mainToolBar->addAction(ui->actionNew);
    ui->mainToolBar->addAction(ui->actionClose);
    ui->mainToolBar->addSeparator();
    ui->mainToolBar->addAction(m_undoAction);
    ui->mainToolBar->addAction(m_redoAction);
    ui->mainToolBar->addSeparator();
}

void MainWindow::initToolsWidgets()
{
    QWidget* pContentWidget = new QWidget;

    QDockWidget* pToolsDock = new QDockWidget(tr("Tools"), this);
    pToolsDock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea);
    pToolsDock->setMinimumWidth(200);
    pToolsDock->setMaximumWidth(200);

    m_toolsLayout = new QVBoxLayout(pContentWidget);
    m_toolsWidget = new ToolsWidget;

    m_toolsLayout->addWidget(m_toolsWidget);
    m_toolsLayout->addItem(new QSpacerItem(20, 2000, QSizePolicy::Minimum, QSizePolicy::Expanding));

    pToolsDock->setWidget(pContentWidget);
    addDockWidget(Qt::LeftDockWidgetArea, pToolsDock);

    m_toolActionGroup = new QActionGroup(this);
    connect(ui->actionShowHideTools, SIGNAL(triggered(bool)), pToolsDock, SLOT(setVisible(bool)));
    ui->actionShowHideTools->setChecked(true);
    connect(pToolsDock, SIGNAL(visibilityChanged(bool)), ui->actionShowHideTools, SLOT(setChecked(bool)));
}

void MainWindow::initDocumentsView()
{
    m_viewDocuments = new ViewDocuments(this);

    connect(ui->actionShowHideDocumentsView, SIGNAL(triggered(bool)), m_viewDocuments, SLOT(setVisible(bool)));
    ui->actionShowHideTools->setChecked(false);

    connect(m_viewDocuments, SIGNAL(visibilityChanged(bool)), ui->actionShowHideDocumentsView, SLOT(setChecked(bool)));

    connect(m_viewDocuments, SIGNAL(closeDocument(QPointer<Document>)),
            this, SLOT(onCloseDocument(QPointer<Document>)));
}

void MainWindow::initDrawingViewContainer()
{
    m_drawingViewContainer = new DrawingViewContainer;
    setCentralWidget(m_drawingViewContainer);
    connect(m_drawingViewContainer, SIGNAL(closeDocument(QPointer<Document>)),
            this, SLOT(onCloseDocument(QPointer<Document>)));
}

void MainWindow::initStatusBar()
{
    m_zoomSlider = new QSlider(Qt::Horizontal, this);
    m_zoomSlider->setRange(10, 500);
    m_zoomSlider->setValue(100);
    m_zoomSlider->setTickPosition(QSlider::TicksBelow);

    m_zoomSlider->setMinimumWidth(150);
    m_zoomSlider->setMaximumWidth(150);
    QLabel* pZoomLabel = new QLabel("Zoom:", this);
    QHBoxLayout* pStatusLayout = new QHBoxLayout;
    pStatusLayout->addSpacerItem(new QSpacerItem(20, 10, QSizePolicy::Expanding, QSizePolicy::Fixed));
    pStatusLayout->addWidget(pZoomLabel);
    pStatusLayout->addWidget(m_zoomSlider);

    QWidget* pStatusWidget = new QWidget(this);
    pStatusWidget->setLayout(pStatusLayout);
    statusBar()->addPermanentWidget(pStatusWidget);

    m_zoomSlider->setDisabled(true);
    connect(&Application::app(), SIGNAL(documentCreated(QPointer<Document>)),
            this, SLOT(updateWidgetsDependentOfDocumentExistion(QPointer<Document>)));

    connect(&Application::app(), SIGNAL(documentRemoved(QPointer<Document>)),
            this, SLOT(updateWidgetsDependentOfDocumentExistion(QPointer<Document>)));
}

void MainWindow::initMainWindowProperties()
{
    setWindowTitle("QCad");
    setWindowState(Qt::WindowMaximized);

    QFile file("qss\\style.qss");
    file.open(QFile::ReadOnly);
    QString styleSheet = QLatin1String(file.readAll());

    qApp->setStyleSheet(styleSheet);
}

void MainWindow::initUndoRedo()
{
    QPointer<QUndoGroup> undoGroup = Application::app().undoGroup();
    Q_ASSERT(undoGroup);
    m_undoAction = undoGroup->createUndoAction(&Application::app(), "Undo");
    m_redoAction = undoGroup->createRedoAction(&Application::app(), "Redo");

    m_undoAction->setIcon(QIcon(":/resources/icons/mainToolbar/undo.png"));
    m_redoAction->setIcon(QIcon(":/resources/icons/mainToolbar/redo.png"));

    m_undoAction->setShortcut(Qt::Key_Z | Qt::CTRL);
    m_redoAction->setShortcut(Qt::Key_Y | Qt::CTRL);
}

void MainWindow::on_actionNew_triggered()
{
    DlgNewDocument dlgNewDoc;

    if(dlgNewDoc.exec() == QDialog::Accepted)
    {
        QPointer<Document> doc = Application::app().createDocument();
        doc->setTitle(dlgNewDoc.documentTitle());
        m_drawingViewContainer->addDocument(doc);
    }
}

void MainWindow::onToolCategoryAdded(QPointer<ToolCategory> toolCategory)
{
    ui->menuTools->addMenu(toolCategory->icon(), toolCategory->name());
    m_toolsWidget->addCategoryTab(toolCategory);
}

void MainWindow::onToolAdded(QPointer<Tool> tool)
{
    QPointer<ToolCategory> category = tool->toolCategory();
    QObjectList children = ui->menuTools->children();

    QMenu* pOwnerMenu = 0;
    foreach(QObject* pObj, children)
    {
        if(QMenu* pMenu = qobject_cast<QMenu*>(pObj))
        {
            if(pMenu->title() == category->name())
            {
                pOwnerMenu = pMenu;
                break;
            }
        }
    }
    Q_ASSERT(pOwnerMenu);

    ToolAction* pAction = new ToolAction ;
    pAction->setText(tool->name());
    pAction->setIcon(tool->icon());
    pAction->setTool(tool);
    pAction->setCheckable(true);

    connect(pAction, SIGNAL(triggered()), this, SLOT(onToolActionTriggered()));

    pOwnerMenu->addAction(pAction);
    m_toolActionGroup->addAction(pAction);
    m_toolsWidget->addToolButton(pAction, category->name());

    static int first = true;
    if(first)
    {
        pAction->trigger();
        first = false;
    }
}

void MainWindow::onToolActionTriggered()
{
    ToolAction* pAction = static_cast<ToolAction*>(sender());
    QPointer<Tool> tool = qobject_cast<Tool*>(pAction->tool());

    QWidget* propWidget = tool->propertiesWidget();

    if(m_toolsLayout->count() == 3)
    {
        m_toolsLayout->itemAt(1)->widget()->setVisible(false);
        m_toolsLayout->removeItem(m_toolsLayout->itemAt(1));
    }

    if(propWidget)
    {
        m_toolsLayout->insertWidget(1, propWidget);
        propWidget->setVisible(true);
    }

    emit toolChanged(qobject_cast<State*>(tool));
}

void MainWindow::updateWidgetsDependentOfDocumentExistion(QPointer<Document> doc)
{
    const DocumentList& docs = Application::app().documents();

    if(docs.count())
    {
        ui->actionClose->setEnabled(true);
        m_zoomSlider->setEnabled(true);
    }
    else
    {
        ui->actionClose->setEnabled(false);
        m_zoomSlider->setEnabled(false);
    }
}

void MainWindow::onCloseDocument(QPointer<Document> doc)
{
    if(QMessageBox::question(0, "Close Document", "Are you sure you want to close document?",
                             QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) return;

    Application::app().removeDocument(doc);
}

void MainWindow::on_actionClose_triggered()
{
    QPointer<Document> currentDoc = Application::app().activeDocument();
    Q_ASSERT(currentDoc);
    onCloseDocument(currentDoc);
}
